﻿#include"XZip.h"
//字典
//数据版
//写入字典数据到压缩的数组中
static void writeDictionaryData(std::pair<const char, DictionariesValue>& pair, std::vector<char>& gzipData)
{
	size_t currentSize = gzipData.size();//当前字节大小
	auto code = pair.second.code;//编码数组
	size_t codeSize = code->size();//编码大小(字节)
	DictionaryData data = { pair.first,pair.second.count,codeSize };
	gzipData.resize(currentSize + sizeof(DictionaryData) + codeSize);//扩容到可以写入一组数据
	char* LPcurrent = &gzipData[0] + currentSize;//当前可以写入的指针
	memcpy(LPcurrent, &data, sizeof(DictionaryData));//拷贝字典基本数据
	LPcurrent += sizeof(DictionaryData);//移位到后面写入编码
	memcpy(LPcurrent, &code->at(0), codeSize);//拷贝编码
}
//在压缩数据中写入字典
size_t XZip::writeGZipDictionaries()
{
	m_zipData.resize(sizeof(unsigned char) * 2);//调整大小，可以写入标记和字典数量
	unsigned char* LPdata = (unsigned char*)&m_zipData[0];//指向存储的空间
	*LPdata++ = m_Type;//写入文件或目录标记
	//写入字典个数
	*LPdata++ = tree.m_dictionaries.size();//字典长度
	for (auto& data : tree.m_dictionaries)
	{
		writeDictionaryData(data, m_zipData);
	}
	return m_zipData.size();
}

//读取压缩后的数据//构建字典
size_t XZip::readGZipDictionaries(const char* data, const size_t size, size_t offset)
{

	unsigned char* LPdata = (unsigned char*)(data + offset);
	unsigned char type = *LPdata++;//类型
	if (!(type & GZIP))
	{
		std::cout << "Type error" << std::endl;
		return 0;
	}
	m_Type = type;
	unsigned char count = *LPdata++;//字典的DictionaryData数量

	offset += sizeof(sizeof(unsigned char) * 2);
	DictionaryData* DictionData = (DictionaryData*)(data + offset);//字典数据
	for (size_t i = 0; i < count; i++)
	{
		DictionariesValue& value = tree.dictionaries()[DictionData->ch];
		size_t codeSize = DictionData->codeSize;//编码大小字节
		value.count = DictionData->count;
		auto code = new std::vector<char>;
		value.code = code;
		code->resize(codeSize);
		offset += sizeof(DictionaryData);//指向写入的哈夫曼编码
		memcpy(&code->at(0), data + offset, codeSize);
		offset += codeSize;//指向下一组数据
		DictionData = (DictionaryData*)(data + offset);//重新定位指针
		if (offset > size)//数据跑完了，还没结束，数据有问题
			return 0;
	}
	return offset;
}
//从文件读取压缩后的数据//构建字典
size_t XZip::readGZipDictionaries(std::fstream& readFile)
{
	unsigned char type = 0;//类型
	if (sizeof(unsigned char) != readFile.read((char*) & type, sizeof(unsigned char)).gcount())//文件有问题
	{
		return 0;
	}
	if (!(type & GZIP))
	{
		std::cout << "Type error" << std::endl;
		return 0;
	}
	m_Type = type;
	unsigned char count =0;//字典的DictionaryData数量
	if (sizeof(unsigned char) != readFile.read((char*)&count, sizeof(unsigned char)).gcount())//文件有问题
	{
		return 0;
	}
	for (size_t i = 0; i < count; i++)
	{
		//读取字典信息
		DictionaryData DictionData ;
		if (sizeof(DictionaryData) != readFile.read((char*)&DictionData, sizeof(DictionaryData)).gcount())//文件有问题
			return 0;
		
		//创建编码内存空间
		DictionariesValue& value = tree.dictionaries()[DictionData.ch];
		size_t codeSize = DictionData.codeSize;//编码大小字节
		value.count = DictionData.count;
		auto code = new std::vector<char>;
		value.code = code;
		code->resize(codeSize);
		//读取编码
		if (codeSize != readFile.read((char*) & code->at(0), codeSize).gcount())//文件有问题
			return 0;
	}

	return readFile.tellg();
}